package cn.openea.perpartner.componet.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.openea.perpartner.common.core.text.Convert;
import cn.openea.perpartner.common.core.utils.PageUtils;
import cn.openea.perpartner.common.core.web.page.TablePage;
import cn.openea.perpartner.componet.util.Tools;
import cn.openea.perpartner.componet.web.entity.HisMsg;
import cn.openea.perpartner.componet.web.entity.InsMsg;
import cn.openea.perpartner.componet.web.entity.vo.MsgResponseVo;
import cn.openea.perpartner.componet.web.mapper.HisMsgMapper;
import cn.openea.perpartner.componet.web.mapper.MsgMapper;
import cn.openea.perpartner.componet.web.service.ITemplateMsgService;
import cn.openea.perpartner.componet.web.vo.MsgQueryVo;
import cn.openea.perpartner.componet.web.vo.R;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @Name:
 * @author: Mr.Yun
 * @Created: 2023/2/15 17:27
 */
@Slf4j
@Service
public class ITemplateMsgServiceImpll extends ServiceImpl<MsgMapper, InsMsg> implements ITemplateMsgService {

    @Value("${bpm.rest.url}")
    private String bpmRestUrl;
    @Autowired
    HisMsgMapper hisMsgMapper;
    private static final String UUID_REGEX = "^[0-9a-fA-F]{32}$";

    @Override
    public R selectListByPage(MsgQueryVo queryVo) {
        PageUtils.startPage();
        QueryWrapper queryWrapper = createdWrapper(queryVo);
        List<InsMsg> msgList = baseMapper.selectAllList(queryWrapper);
        // 查未读数
        queryWrapper.eq("already_read", "N");
        Long unread = baseMapper.selectAllCount(queryWrapper);
        return R.ok().put("total", new PageInfo(msgList).getTotal()).put("unread", unread).put("list", msgList.stream().map(msg -> MsgResponseVo.builder()
                .id(Convert.toStr(msg.getId()))
                .showType(msg.getUserid())
                .showSubject(msg.getFirst())
                .endTime(msg.getCreateTime())
                .pagepath(msg.getPagepath())
                .url(msg.getMsgstatus())
                .alreadyRead(msg.getAlreadyRead())
                .docUnid(msg.getDocUnid())
                .build()).collect(java.util.stream.Collectors.toList()));
    }

    @Override
    public R selectLocalAndBpmList(MsgQueryVo queryVo) {
        PageUtils.startPage();
        LambdaQueryWrapper<InsMsg> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(InsMsg::getUserid, queryVo.getUserid());
        wrapper.eq(InsMsg::getDeleted, "0");
        if (StrUtil.isNotBlank(queryVo.getSearchField())) {
            wrapper.and(i -> i.like(InsMsg::getFirst, queryVo.getSearchField())
                    .or().like(InsMsg::getKeyword1, queryVo.getSearchField())
                    .or().like(InsMsg::getKeyword2, queryVo.getSearchField())
                    .or().like(InsMsg::getKeyword3, queryVo.getSearchField())
                    .or().like(InsMsg::getKeyword4, queryVo.getSearchField())
                    .or().like(InsMsg::getKeyword5, queryVo.getSearchField())
                    .or().like(InsMsg::getKeyword6, queryVo.getSearchField())
                    .or().like(InsMsg::getDocUnid, queryVo.getSearchField()));
        }
        List<InsMsg> msgList = list(wrapper);
        List<MsgResponseVo> msgResponseVoList = msgList.stream().map(msg -> MsgResponseVo.builder()
                .id(Convert.toStr(msg.getId()))
                .showType(msg.getUserid())
                .showSubject(msg.getFirst())
                .endTime(msg.getCreateTime())
                .pagepath(msg.getPagepath())
                .url(msg.getMsgstatus())
                .alreadyRead(msg.getAlreadyRead())
                .docUnid(msg.getDocUnid())
                .build()).collect(java.util.stream.Collectors.toList());
        HashMap<String, Object> params = new HashMap<>();
        params.put("appid", "AppletsPro");
        params.put("wf_num", "R_AppletsPro_B003");
        params.put("userId", queryVo.getUserid());
        params.put("pageNum", TablePage.buildPageRequest().getPageNum());
        params.put("pageSize", TablePage.buildPageRequest().getPageSize());
        params.put("searchStr", queryVo.getSearchField());
        JSONObject jsonObject = doBpmRequest(params);
        msgResponseVoList.addAll(JSON.parseArray(jsonObject.getString("data"), MsgResponseVo.class));
        // 按时间倒序
        msgResponseVoList.sort((o1, o2) -> o2.getEndTime().compareTo(o1.getEndTime()));
        return R.ok().put("total", new PageInfo(msgList).getTotal()).put("list", msgResponseVoList);
    }

    @Override
    public R updateMsgReadById(Long msgid) {
        InsMsg msg = new InsMsg();
        msg.setId(msgid);
        msg.setAlreadyRead("Y");
        R r = updateMsgById(msg);
        if (r.getCode() == 201) {
            HisMsg hisMsg = new HisMsg();
            hisMsg.setId(msgid);
            hisMsg.setAlreadyRead("Y");
            r = updateMsgById(hisMsg);
        }
        log.info("{}", r);
        return r;
    }

    @Override
    public R deleteMarkMsgById(Long msgid) {
        InsMsg msg = new InsMsg();
        msg.setId(msgid);
        msg.setDeleted("1");
        R r = updateMsgById(msg);
        if (r.getCode() == 201) {
            HisMsg hisMsg = new HisMsg();
            hisMsg.setId(msgid);
            hisMsg.setDeleted("1");
            r = updateMsgById(hisMsg);
        }
        return r;
    }

    @Override
    public R getMsgById(Long msgid) {
        R r = R.error();
        try {
            InsMsg insMsg = baseMapper.selectById(msgid);
            if (BeanUtil.isNotEmpty(insMsg)) {
                r = R.ok().put("message", insMsg);
            } else {
                HisMsg hisMsg = hisMsgMapper.selectById(msgid);
                r = R.ok().put("message", hisMsg);
            }
        } catch (Exception e) {
            r.setMsg(e.getMessage());
        }
        return r;
    }

    @Override
    public List<InsMsg> selecSendMsgtTopList() {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("msgstatus", "S");
        queryWrapper.orderByAsc("id");
        IPage<InsMsg> iPage = baseMapper.selectPage(new Page<>(1, 50), queryWrapper);
        return iPage.getRecords();
    }

    @Override
    public R updateLocalAndBpmMsgReadById(String msgid) {
        if (StrUtil.isBlank(msgid)) {
            return R.error().put("msg", "msgid is not allowed to be empty!");
        }
        R r = R.ok();
        if (isValidUUID(msgid)) {
            HashMap<String, Object> params = new HashMap<>();
            params.put("appid", "AppletsPro");
            params.put("wf_num", "R_AppletsPro_B015");
            params.put("WF_OrUnid", msgid);
            JSONObject jsonObject = doBpmRequest(params);
            int code = Convert.toInt(jsonObject.getString("code"));
            if (code != 200) {
                r = R.error();
            }
            r.put("msg", jsonObject.getString("msg"));
        } else {
            r = updateMsgReadById(Convert.toLong(msgid));
        }
        return r;
    }

    @Override
    public R updateLocalAndBpmMsgUnReadById(String msgid) {
        if (StrUtil.isBlank(msgid)) {
            return R.error().put("msg", "msgid is not allowed to be empty!");
        }
        R r = R.ok();
        if (isValidUUID(msgid)) {
            HashMap<String, Object> params = new HashMap<>();
            params.put("appid", "AppletsPro");
            params.put("wf_num", "R_AppletsPro_B050");
            params.put("WF_OrUnid", msgid);
            JSONObject jsonObject = doBpmRequest(params);
            int code = Convert.toInt(jsonObject.getString("code"));
            if (code != 200) {
                r = R.error();
            }
            r.put("msg", jsonObject.getString("msg"));
        } else {
            InsMsg msg = new InsMsg();
            msg.setId(Convert.toLong(msgid));
            msg.setAlreadyRead("N");
            r = updateMsgById(msg);
        }
        return r;
    }

    @Override
    public R deleteMarkLocalAndBpmMsgById(String msgid) {
        if (StrUtil.isBlank(msgid)) {
            return R.error().put("msg", "msgid is not allowed to be empty!");
        }
        R r = R.ok();
        if (isValidUUID(msgid)) {
            HashMap<String, Object> params = new HashMap<>();
            params.put("appid", "AppletsPro");
            params.put("wf_num", "R_AppletsPro_B051");
            params.put("WF_OrUnid", msgid);
            JSONObject jsonObject = doBpmRequest(params);
            int code = Convert.toInt(jsonObject.getString("code"));
            if (code != 200) {
                r = R.error();
            }
            r.put("msg", jsonObject.getString("msg"));
        } else {
            r = deleteMarkMsgById(Convert.toLong(msgid));
        }
        return r;
    }

    /**
     * 按条件生成QueryWrapper条件，只查未被标记为删除的记录
     *
     * @param queryVo 条件
     * @return
     */
    private QueryWrapper createdWrapper(MsgQueryVo queryVo) {
        QueryWrapper queryWrapper = new QueryWrapper();
        if (Tools.isNotBlank(queryVo.getUserid())) {
            queryWrapper.eq("userid", queryVo.getUserid());
        }
        queryWrapper.eq("deleted", "0");
        if (queryVo.isIdAsc()) {
            // 如果这里是按ID升序
            queryWrapper.orderByAsc("id");
        } else {
            queryWrapper.orderByDesc("id");
        }
        return queryWrapper;
    }

    /**
     * 按消息id更新消息
     *
     * @param msg 需要更新的消息
     * @return
     */
    private R updateMsgById(InsMsg msg) {
        R r = R.error();
        try {
            int i = baseMapper.updateById(msg);
            if (i == 1) {
                r = R.ok();
            }
        } catch (Exception e) {
            r.setMsg(e.getMessage());
        }
        return r;
    }

    private R updateMsgById(HisMsg msg) {
        R r = R.error();
        try {
            int i = hisMsgMapper.updateById(msg);
            if (i == 1) {
                r = R.ok();
            }
        } catch (Exception e) {
            r.setMsg(e.getMessage());
        }
        return r;
    }

    private JSONObject doBpmRequest(HashMap<String, Object> params) {
        HttpResponse resp = HttpRequest.post(bpmRestUrl)
                .header("sysid", "SysAdmin")
                .header("syspwd", "pass")
                .header("userId", "admin")
                .form(params)
                .execute();
        return JSON.parseObject(resp.body());
    }

    public static boolean isValidUUID(String uuid) {
        boolean isValid = false;
        if (!Pattern.matches(UUID_REGEX, uuid)) {
            isValid = uuid.length() > 20;
        }
        return isValid;
    }
}
